package com.swust.dumpling.commons.file;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import com.swust.dumpling.commons.file.zip.ZipEntry;
import com.swust.dumpling.commons.file.zip.ZipOutputStream;

/**
 * just for compression
 * @author swust-cs-Dong6 B425
 * */
public class ZipFile {
	
	public static String S = "\\".equals(File.separator) ? "\\" : "/";
	
	public static int BUFFERED_SIZE = 1 << 14;
	
	/*static long begin = System.currentTimeMillis();*/
	
	/**
	 * 使用byte数组的效率要远高于使用int储存二进制流的效率
	 * <p>
	 * <code>
	 * int * readSingle(JNIEnv *env, jobject this, jfieldID fid) {
	 * 		int nread;
	 * 		char ret;
	 * 		FD fd = GET_FD(this, fid);
	 * 		nread = IO_Read(fd, &ret, 1);
	 * 		if (nread == 0) {  //EOF 
	 * 			return -1;
	 * 		} else if (nread == JVM_IO_ERR) // error { 
	 * 			JNU_ThrowIOExceptionWithLastError(env, "Read error");
	 * 		} else if (nread == JVM_IO_INTR) {
	 * 			JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
	 * 		}
	 * 		return ret & 0xFF;
	 * }
	 * </code>
	 * */
	private static void putDirectory(String directory , ZipOutputStream zos , String cur)
			throws IOException {
		File dir = new File(directory);
		if (!dir.exists() || !dir.isDirectory()) 
			throw new RuntimeException("DIRECTORY ERROR ! ");
		File[] list = dir.listFiles();
		FileInputStream fis = null;
		byte[] t = new byte[BUFFERED_SIZE];
		for (File file : list) {
			if (file.isDirectory()) {
				
				/*下面这句话会导致被压缩后的文件夹在直接打开之时出现一个多余的文件指向.而那是不需要存在的,尽管压缩后那个指向不在了
				 * The following sentence will cause the file to be compressed directly open the folder 
				 * appear when an extra file points, while it is not need to exist, 
				 * and after that point even though the compression is gone */
				/*zos.putNextEntry(new ZipEntry(("".equals(cur) ? "" : cur + S) + file.getName() + S));*/
				
				String path = file.getAbsolutePath();
				String str = S.equals("\\") ? "\\\\" : S;
				String tmp = path.split(str)[path.split(str).length - 1];
				
				tmp = new String(tmp.getBytes("UTF-8") , "UTF-8");
				
				/* 将文件压缩到它的文件夹里面去
				 * compress the file to a folder inside */
				
				putDirectory(file.getAbsolutePath() + S , zos , ("".equals(cur) ? "" : cur + S) + tmp);
				
			} else {
				
				String tmp = file.getName();
				tmp = new String(tmp.getBytes("UTF-8") , "UTF-8");
				
				zos.putNextEntry(new ZipEntry( ("".equals(cur) ? "" : cur + S) + tmp));
				
				/*System.out.println(file.getName());
				System.out.println(System.currentTimeMillis() - begin + "\n");*/
				
				fis = null;
				fis = new FileInputStream(file);
				while (( fis.read(t)) != -1) {
					zos.write(t);
					zos.flush();
				}
				fis.close();
			}
		}
	}
	
	/**
	 * 对整个文件夹的压缩
	 * @param directory the directory to be compressed
	 * @param file output zip file
	 * @throws IOException
	 * */
	public static void 
			createZip(String directory , File file) throws IOException {
		ZipOutputStream zos = 
				new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
		putDirectory( directory , zos ,"");
		zos.close();
	}
	/**
	 * 对一个文件链表的压缩
	 * @param fileList a list of file
	 * @param zip 被打包后的文件
	 * @return 打包后的放在路径下的zip文件
	 * @throws IOException 
	 * */
	public static File 
			createZip(List<File> fileList , File zip) throws IOException
	{		
		if (! zip.exists()) 
			zip.createNewFile();
		ZipOutputStream zos = 
				new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zip)));
		FileInputStream fis = null;
		byte[] t = new byte[BUFFERED_SIZE];
		for (File file : fileList) {
			if (file.isDirectory()) {
				putDirectory(file.getAbsolutePath(), zos, file.getName());
			} else {
				zos.putNextEntry(new ZipEntry(file.getName()));

				/*System.out.println(file.getName());
				System.out.println(System.currentTimeMillis() - begin + "\n");*/
				
				fis = new FileInputStream(file);
				while( (fis.read(t)) != -1)
					zos.write(t);
				fis.close();
			}
		}
		zos.flush();
		zos.close();
		
		return zip;
	}
	
	/*public static void main(String[] args) throws IOException
	{
		String dir = "C:\\Users\\xia\\Desktop\\tmp\\gif";
		
		File file = new File("C:\\Users\\xia\\Desktop\\tt.zip");
		
		createZip(dir, file);
		
		String t = "测试lizi";
		byte b = (byte) (1 << 7);
		System.out.println(b);
		byte[] bb = t.getBytes("gbk");
		System.out.println(bb.length);
		for (int i = 0 ; i < bb.length ; i ++) {
			System.out.println( bb[i] );
		}
		//-----------------\\
		t = new String (bb , "Unicode");
		System.out.println("Unicode : " + t);
		t = new String (bb , "GB2312");
		System.out.println("GB2312 : " + t);
		t = new String (bb , "UTF-8");
		System.out.println("UTF-8 : " + t);
		t = new String (bb , "ISO-8859-1");
		System.out.println("ISO-8859-1 :" + t);
	}*/
}
